package com.util;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.util.StringUtils;


import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author zqw
 * @date 2019/5/20 11:18
 */
public class DateUtils {
    public static final String YYYY_MM_DD = "yyyy-MM-dd";
    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    /**
     * 解析日期
     * @param date
     * @param pattern
     * @return
     */
    public static Date parseDate(String date,String pattern){
        try{
            if(!StringUtils.isEmpty(date)){
                return  org.apache.commons.lang3.time.DateUtils.parseDate(date,pattern);
            }
        }catch (Exception e){}
        return null;
    }

    /**
     * 解析日期
     * @param date
     * @param pattern
     * @return
     */
    public static String format(Date date,String pattern){
        try{
            if(date != null){
                return DateFormatUtils.format(date,pattern);
            }
        }catch (Exception e){}
        return null;
    }

    /**
     * 解析日期
     * @param date
     * @return
     */
    public static String formatDate(String date){
        try{
            if(!StringUtils.isEmpty(date)){
                if(date.length() > 10){
                    //yyyy-MM-dd
                    return date.substring(0,10);
                }
            }
            return date;
        }catch (Exception e){}
        return null;
    }

    public static Date getNow(){
        return getNow(TimeZone.getDefault());
    }

    public static Date getNow(TimeZone timeZone){
        return Calendar.getInstance(timeZone).getTime();
    }

    public static Date getNow(String timeZoneId){
        TimeZone timeZone = TimeZone.getTimeZone(timeZoneId);
        return getNow(timeZone);
    }

    /**
     * 获取日期的一天开始时间
     * @param date
     * @return
     */
    public static Date getDayOfBegin(Date date){
        if(date != null){
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            setDayOfBegin(calendar);
            return calendar.getTime();
        }
        return null;
    }

    /**
     * 获取日期的一天结束时间
     * @param date
     * @return
     */
    public static Date getDayOfEnd(Date date){
        if(date != null){
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            setDayOfEnd(calendar);
            return calendar.getTime();
        }
        return null;
    }

    /**
     * 获取日期的day之后的开始时间，如果为负数表示之前几天的开始时间
     * @param date
     * @return
     */
    public static Date getNearDayStartDate(Date date,int day){
        if(date != null){
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);

            //先设置为多少天之后
            calendar.add(Calendar.DAY_OF_YEAR,day);
            //再设置为一天的开始时间
            setDayOfBegin(calendar);
            return calendar.getTime();
        }
        return null;
    }

    /**
     * 获取日期的day之后的结束时间，如果为负数表示之前几天的结束时间
     * @param date
     * @return
     */
    public static Date getNearDayEndDate(Date date,int day){
        if(date != null){
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            //先设置为多少天之后
            calendar.add(Calendar.DAY_OF_YEAR,day);
            //再设置为一天的结束时间
            setDayOfEnd(calendar);
            return calendar.getTime();
        }
        return null;
    }

    /**
     * 获取日期的week之后的开始时间，如果为负数表示之前几周的开始时间
     * @param date
     * @return
     */
    public static Date getNearWeekStartDate(Date date,int week){
        if(date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            //先设置为几周之后
            calendar.add(Calendar.WEEK_OF_YEAR,week);
            //再设置为星期1
            calendar.set(Calendar.DAY_OF_WEEK,2);
            //再设置为一天的开始时间
            setDayOfBegin(calendar);
            return calendar.getTime();
        }
        return null;
    }

    /**
     * 获取日期的week周之后的结束时间，如果为负数表示之前几周的结束时间
     * @param date
     * @return
     */
    public static Date getNearWeekEndDate(Date date,int week){
        if(date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            //先设置为几周之后
            calendar.add(Calendar.WEEK_OF_YEAR,week);
            //再设置为星期1
            calendar.set(Calendar.DAY_OF_WEEK,2);
            //再加7天
            calendar.add(Calendar.DAY_OF_YEAR,6);
            //再设置为一天的结束时间
            setDayOfEnd(calendar);
            return calendar.getTime();
        }
        return null;
    }

    /**
     * 获取日期的month个月之后的开始时间，如果为负数表示之前几个月的开始时间
     * @param date
     * @return
     */
    public static Date getNearMonthStartDate(Date date,int month){
        if(date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);

            //先设置为几个月之后
            calendar.add(Calendar.MONTH,month);
            //设置为每个月的开始日期
            calendar.set(Calendar.DAY_OF_MONTH,1);
            //设置为当天的开始时间
            setDayOfBegin(calendar);
            return calendar.getTime();
        }
        return null;
    }

    /**
     * 获取日期的month个月之后的结束时间，如果为负数表示之前几个月的结束时间
     * @param date
     * @return
     */
    public static Date getNearMonthEndDate(Date date,int month){
        if(date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            //设置为x+1个月之后，
            calendar.add(Calendar.MONTH,month+1);
            calendar.set(Calendar.DAY_OF_MONTH,1);
            //减一天即为该月份的最后一天
            calendar.add(Calendar.DAY_OF_YEAR,-1);
            //设置当天的开始时间
            setDayOfEnd(calendar);
            return calendar.getTime();
        }
        return null;
    }

    /**
     * 获取日期的quarter个季度之后的开始时间，如果为负数表示之前几个季度的开始时间
     * @param date
     * @return
     */
    public static Date getNearQuarterStartDate(Date date,int quarter){
        if(date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);

            //哪个几个月
            int whichMonth = calendar.get(Calendar.MONTH);
            //目前处于哪个季度
            int whichQuarter = whichMonth/(3+1)+1;
            //该季度的开始月份
            int quarterMonthEnd = whichQuarter*3;
            int quarterMonthStart = quarterMonthEnd-2;

            //需要加的月份数
            int addMonth = quarter*3-1;
            //先设置为本季度的开始月份
            calendar.set(Calendar.MONTH,quarterMonthStart);
            //加几个月
            calendar.add(Calendar.MONTH,addMonth);
            calendar.set(Calendar.DAY_OF_MONTH,1);
            //设置为当天的开始时间
            setDayOfBegin(calendar);
            return calendar.getTime();
        }
        return null;
    }

    /**
     * 获取日期的quarter个季度之后的开始时间，如果为负数表示之前几个季度的开始时间
     * @param date
     * @return
     */
    public static Date getNearQuarterEndDate(Date date,int quarter){
        if(date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);

            //哪个几个月
            int whichMonth = calendar.get(Calendar.MONTH);
            //目前处于哪个季度
            int whichQuarter = whichMonth/(3+1)+1;
            //该季度的开始月份
            int quarterMonthEnd = whichQuarter*3;

            //需要加的月份数
            int addMonth = quarter*3-1;
            //先设置为本季度的开始月份
            calendar.set(Calendar.MONTH,quarterMonthEnd);
            //加x+1个月
            calendar.add(Calendar.MONTH,addMonth+1);
            calendar.set(Calendar.DAY_OF_MONTH,1);
            calendar.add(Calendar.DAY_OF_YEAR,-1);
            //设置为当天的开始时间
            setDayOfEnd(calendar);
            return calendar.getTime();
        }
        return null;
    }


    public static Date addMinutes(Date date,int minutes){
        if(date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.MINUTE,minutes);
            return calendar.getTime();
        }
        return date;
    }

    public static Date addMillis(Date date,int millis){
        if(date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.MILLISECOND,millis);
            return calendar.getTime();
        }
        return date;
    }

    public static Date addDays(Date date,int day){
        if(date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.DATE,day);
            return calendar.getTime();
        }
        return date;
    }

    public static Date parse(String date, String pattern){
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
            return simpleDateFormat.parse(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取两个日期之间的秒数
     * @param before
     * @param after
     * @return
     */
    public static long getSecondSpace(Date before, Date after) {
        return ((after.getTime() - before.getTime()) / 1000);
    }

    /**
     * 获取星期几：1 星期一，2 星期二，3 星期三，4星期四，5星期五，6星期六，7星期天
     *
     * @param date
     * @return
     */
    public static int getWeekday(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)-1;
        return dayOfWeek == 0 ? 7:dayOfWeek;
    }

    //////////////////////////// 私有方法 ////////////////////////////

    /**
     * 设置日期为一天的开始时间
     * @param calendar
     * @return
     */
    private static void setDayOfBegin(Calendar calendar){
        if(calendar != null){
            calendar.set(Calendar.HOUR_OF_DAY,0);
            calendar.set(Calendar.MINUTE,0);
            calendar.set(Calendar.SECOND,0);
            calendar.set(Calendar.MILLISECOND,0);
        }
    }

    /**
     * 设置日期的为结束时间
     * @param calendar
     * @return
     */
    private static void setDayOfEnd(Calendar calendar){
        if(calendar != null){
            calendar.set(Calendar.HOUR_OF_DAY,23);
            calendar.set(Calendar.MINUTE,59);
            calendar.set(Calendar.SECOND,59);
            calendar.set(Calendar.MILLISECOND,999);
        }
    }

    /**
     * 获取两个日期相隔的天数
     * @param before
     * @param after
     * @return
     */
    public static int getDaySpace(Date before, Date after) {
        return (int)((after.getTime() - before.getTime()) / (24 * 60 * 60 * 1000));
    }

    /**
     * 将 转换 date 格式
     * @param date
     * @param pattern
     * @return
     */
    public static Date parseDate(Date date,String pattern){
        String strDate = format(date, pattern);
        return parseDate(strDate,pattern);
    }

    public static void main(String[] args){

        Date now = getNow();


    }

}
